The data variable (represented by the UADataVariable Class) is the central object in OPC UA generic/data server. Depending on the purpose of the data variable, it provides means to read data, subscribe data, and/or write data. It has multiple properties that influence its behavior, such as data type, array dimensions, access right (whether it is readable, writable, or both), etc.
When you develop an OPC server using OPC Wizard, you need to define the data variables of the server, and how they relate together. In addition, the properties and behavior of each data variable needs to be defined as well. This is called the configuration of the data variable. You can always configure your data variables by setting the various individual properties of the UADataVariable Class instance, and optionally hooking handlers to its events. The data variables in typical servers are, however, usually configured in certain common ways. The OPC Wizard provides extension methods that allow easier configuration of such typical data variables.
The extension methods for data variable configuration are located in the UADataVariableExtension Class. The allow for fluent configuration, i.e. each method returns the reference to the data variable it is operating on, and the method calls can therefore be chained.
Some data variable configuration methods exist in multiple overloads. Such methods have the same purpose, but allow different combinations of how the arguments are specified, and their defaults. In some cases, a method overload exists that has generic type parameter which typically corresponds to the type the data variable will have. In such case, the method overload can determine the OPC data type and array rank from this generic type parameter. In addition, in many cases you do not even have to specify it, because it can be inferred from the code. For example, if you pass "read value function" (a function that implements the reading of data variable's value) that returns a String to the data variable configuration method, the method will determine that the OPC type of the data variable will also be String, and the OPC value rank will specify that the data variable is a scalar (not an array). For more complicated cases, other method overloads then allow you to specify the OPC data type and other parameters explicitly using method arguments.
The configuration methods can be categorized as either "primitive" (they typically that modify just one or two members of the data variable) or "composite" (for full configuration of the data variable). We will start with discussion of the primitive configuration methods, because it is good for understanding of how the things are put together; however, your code will probably mainly use the composite configuration methods, because using them gives short and clear code.
For information related to configuration of the data type, see Variable Data Type Considerations.
The primitive configuration methods modify only one member of the data variable, or a closely tight group of members. You will normally use more of the primitive configuration methods together, in order to achieve the configuration that you want. Also, primitive configuration methods can sometimes be used to "post-configure" (i.e. further modify) the data variable that has been configured using the composite methods (described further below).
Whenever you can, look for a composite configuration method to configure the data variable according to your needs - and you will usually find it. Only if there is no composite configuration method that can be used, use the primitive configuration methods.
The following table lists the primitive configuration methods available and their purpose. The table also indicates which properties or events of the data variable are affected and how.
Method or Group of Method Overloads | Description | ArrayDimensions Property | DataTypeId Property | HandleChild-Nodes Property | MinimumSampling-Interval Property | PropagateRead Property | PropagateWrite Property | Read Event | IsReadable Property | ReadAttribute-Data Property | IsWritable Property, WritableSource-Timestamp Property, WritableStatusCode Property |
Write Event | WriteAttribute-Data Property | WriteLoopback Property |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ProcessRead Method | Specifies that reads of this data variable will be processed by the specified read function. |
⨯ |
⨯ |
false |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
ProcessWrite Method | Specifies that writes of this data variable will be processed by the specified write function. |
⨯ |
⨯ |
false |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
Readable Methods | Modifies the data variable to be readable or not. |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
SetArrayDimensions Method | Sets the array dimensions of this data variable. |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
SetArrayRank Method | Sets the array rank of this data variable. |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
SetMinimumSamplingInterval Method | Sets the minimum sampling interval of this data variable. |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
ValueType Methods | Makes the data variable to use the specified value type. |
✓ |
✓ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
✓ |
⨯ |
Writable Methods | Modifies the data variable to be writable or not, also allowing to specify whether its status code and source timestamp will be writable. |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
✓ |
⨯ |
⨯ |
⨯ |
In order to make a read-only data variable (prevent writing to the data variable), call the Writable Method with its argument set to false.
In order to make a write-only data variable (prevent reading from the data variable), call the Readable Method with its argument set to false.
There is also the SetState<TNode> Method, which allows you to modify the State Property of any node. You can use this method to set the state object in the node to any reference (object) that has relation to the node in your project. This way, you can associate your own objects with the nodes.
The composite configuration methods are build on top of the primitive configuration methods. They provide a way to define the most common data variable behaviors without having to bother with setting multiple properties and/or hooking to event of the data variable object.
Methods exist for 4 distinct types of data variable behavior:
The methods operate on the data variable itself, and assume that the behavior of each data variable will be defined separately. In some servers, it is beneficial to define the same behavior for a specific sub-tree of data variables, on some parent folder level (or on the server level). In such cases you need to hook events or override methods on the parent nodes, and the composite configuration methods described here are not suitable for this task.
The methods that have "Value" in their name allow you to work simply with the Value part of the node's data, whereas the method without the "Value" in their operate on the whole UAAttributeData Class instance, i.e. also including the status code and timestamp.
In many cases, a call to a single composite configuration method with appropriate parameters is enough to fully configure the data variable. Two method calls are needed if you want to define the code for both "read pull" and "write push". In some cases, a call to a composite configuration methods might be followed by a call to some primitive configuration methods, to "fine-tune" certain data variable properties.
The following table lists the composite configuration methods available and their purpose. The table also indicates which properties or events of the data variable are affected and how.
Method or Group of Method Overloads | Description | ArrayDimensions Property | DataTypeId Property | HandleChild-Nodes Property | MinimumSampling-Interval Property | PropagateRead Property | PropagateWrite Property | Read Event | IsReadable Property | ReadAttribute-Data Property | IsWritable Property, WritableSource-Timestamp Property, WritableStatusCode Property |
Write Event | WriteAttribute-Data Property | WriteLoopback Property |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Constant Methods | Modifies the data variable to provide the specified constant attribute data (value, status code, timestamp), non-writable. |
✓ |
✓ |
⨯ |
false |
⨯ |
⨯ |
true |
✓ |
false, false, false |
⨯ |
⨯ |
⨯ |
|
ConstantValue Methods | Modifies the data variable to provide the specified constant value, non-writable. |
✓ |
✓ |
⨯ |
false |
⨯ |
⨯ |
true |
✓ |
false, false, false |
⨯ |
⨯ |
⨯ |
|
ReadFunction Methods | Modifies the data variable to provide attribute data for the pull data provision model by a specified function. |
✓ |
✓ |
false |
⨯ |
⨯ |
⨯ |
✓ |
true |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
ReadValueFunction Methods | Modifies the data variable to provide value for the pull data provision model by a specified function. |
✓ |
✓ |
false |
⨯ |
⨯ |
⨯ |
✓ |
true |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
ReadWrite Methods | Modifies the data variable to behave as read-write register, with specified initial attribute data (value, status code, timestamp). |
✓ |
✓ |
⨯ |
⨯ |
false |
false |
⨯ |
true |
✓ |
true, true, true |
⨯ |
✓ |
true |
ReadWriteValue Methods | Modifies the data variable to behave as read-write register, with specified initial value. |
✓ |
✓ |
⨯ |
⨯ |
false |
false |
⨯ |
true |
✓ |
true, false, false |
⨯ |
✓ |
true |
WriteFunction Methods | Modifies the data variable for consuming attribute data by a specified function, for the push data consumption model. |
✓ |
✓ |
false |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
true, true, true |
✓ |
⨯ |
⨯ |
WriteValueAction Methods | Modifies the data variable for consuming values by a specified action, for the push data consumption model. |
✓ |
✓ |
false |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
true, false, false |
✓ |
⨯ |
⨯ |
WriteValueFunction Methods | Modifies the data variable for consuming values by a specified function, for the push data consumption model. |
✓ |
✓ |
false |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
⨯ |
true, false, false |
✓ |
⨯ |
⨯ |
The Constant methods modify the data variable to provide the specified constant attribute data (value, status code, timestamp), non-writable.
The data variable is made read-only, and its minimum sampling interval is set to Timeout.Infinite, effectively disabling the sampling. For reads and subscriptions, the data variable will provide always the same attribute data, specified in this method call.
If your constant data should contain a "Good" status code, and take the current time as the timestamp, you can use the ConstantValue method instead.
The ConstantValue methods modify the data variable to provide the specified constant value, non-writable.
The data variable is made read-only, and its minimum sampling interval is set to Timeout.Infinite, effectively disabling the sampling. For reads and subscriptions, the data variable will provide always the same value, specified in this method call. The status code will be "Good", and the timestamp will be the current time of this method call.
If you need a status code different from "Good", or a different timestamp, use the Constant method instead.
Example: Examples - Server OPC UA - Data variable with a constant value
The ProcessRead method specifies that reads of this data variable will be processed by the specified read function.
This method works by adding an event handler to the Read Event event of the data variable.
The ProcessWrite method specifies that writes of this data variable will be processed by the specified write function.
This method works by adding an event handler to the Write Event event of the data variable.
The Readable methods modify the data variable to be readable or not.
In order to configure the data variable, you will typically combine this method with more configuration methods.
Example: Examples - Server OPC UA - Write-only value implemented using an action
The ReadFunction methods modify the data variable to provide attribute data for the Pull Data Provision Model by a specified function.
If the collected data should always contain a "Good" status code, and take the current time as the timestamp, you can use the ReadValueFunction method instead.
Example: Examples - Server OPC UA - Data variable reading using a function
The ReadValueFunction methods modify the data variable to provide value for the Pull Data Provision Model by a specified function.
If the collected data should sometimes have a status code different from "Good", or you do not want to use the current time as the timestamp, use the ReadFunction method instead.
Example: Examples - Server OPC UA - Data variable value reading implemented using a function
The ReadWrite methods modify the data variable to behave as read-write register, with specified initial attribute data (value, status code, timestamp).
This method makes the data variable both readable and writable. The data written to the data variable will become the data subsequently read from the data variable.
This method also makes the status code and source timestamp of the data variable writable, i.e. OPC UA clients will be able to modify their values. If you need a different behavior, call the Writable method subsequently, with desired parameters.
If you want a register that always contains data with "Good" status code (and its timestamp is not writable either), you can use the ReadWriteValue method instead.
Example: Examples - Server OPC UA - Read-write register with initial attribute data
The ReadWriteValue methods modify the data variable to behave as read-write register, with specified initial value.
Example: Examples - Server OPC UA - Read-write register with initial value
The SetArrayDimensions method sets the array dimensions of this data variable.
In order to configure the data variable, you will typically combine this method with more configuration methods.
The SetArrayRank method sets the array rank of this data variable.
In order to configure the data variable, you will typically combine this method with more configuration methods.
The SetMinimumSamplingInterval method sets the minimum sampling interval of this data variable.
In order to configure the data variable, you will typically combine this method with more configuration methods.
Setting the minimum sampling interval to Timeout.Infinite effectively disables the sampling.
Example: Examples - Server OPC UA - Set minimum sampling interval of a data variable
The ValueType methods make the data variable to use the specified value type. The methods also initialize the attribute data (i.e. the ReadAttributeData Property and the WriteAttributeData Property) with a default value for the given data type (otherwise the initial value is null), except when you use an overload that allows to suppress such initialization by a boolean argument.
In order to configure the data variable, you will typically combine this method with more configuration methods.
Example: Examples - Server OPC UA - Provide attribute data by pushing them to the server
Example: Examples - Server OPC UA - Implement variable reading on folder level, with an event
The Writable methods modify the data variable to be writable or not, also allowing to specify whether its status code and source timestamp will be writable.
In order to configure the data variable, you will typically combine this method with more configuration methods.
Example: Examples - Server OPC UA - Read-write register with writable timestamp and status
The WriteFunction methods modify the data variable for consuming attribute data by a specified function, for the Push Data Consumption Model.
The write function accepts the attribute data (an instance of UAAttributeData Class), and returns a status code (an instance of UAStatusCode Class) that indicates the outcome of the OPC UA write. The WriteFunction methods are the most generic extension methods for writing. If you only need to deal with data variable value (and not its status code and/or timestamp), consider using one of the WriteValueFunction or WriteValueAction method overloads, for shorter code and easier programming.
Example: Examples - Server OPC UA - Implement writing using a function
The WriteValueAction methods modify the data variable for consuming values by a specified action, for the Push Data Consumption Model.
Unless the write value action throws a UAStatusCodeException, a "Good" status code will be returned as the outcome of the OPC UA write operation. If the write value action function throws UAStatusCodeException, the StatusCode Property of the exception will become the outcome of the OPC UA write operation. For performance reasons, however, if you ever want to return status codes other than "Good" as OPC UA write operation outcomes, it is recommended that you use one of the WriteValueFunction method overloads instead. With these methods, you specify a write value function that returns the UAStatusCode that is the OPC UA write operation outcome, allowing the status code be passed without the ineffective throwing and catching of the UAStatusCodeException.
Example: Examples - Server OPC UA - Write-only value implemented using an action
The WriteValueFunction methods modify the data variable for consuming values by a specified function, for the Push Data Consumption Model.
The write function returns a UAStatusCode that indicates the outcome of the OPC UA write operation. If the outcome of your write operation should always be "Good", you can make your code a bit simpler by using one of WriteValueAction method overloads instead.
Example: Examples - Server OPC UA - Implement value writing using a function